package com.search.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.base.core.pager.PageBean;
import com.base.core.pager.PageContext;
import com.search.dao.repo.HospitalRepository;
import com.search.entity.Hospital;
import com.search.service.SearchHospitalService;
import com.search.service.dto.SearchHospital;
import com.search.service.dto.SearchHospitalParam;
import org.apache.dubbo.config.annotation.DubboService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

@DubboService(version = "0.0.1-alpha", timeout = 3000, delay = -1)
public class SearchHospitalServiceImpl implements SearchHospitalService {

    @Resource
    private HospitalRepository hospitalRepository;

    private final String DESC = "-1";
    private final String ASC = "1";

    @Override
    public PageBean<SearchHospital> search(SearchHospitalParam searchHospitalParam) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder booleanQueryBuilder = new BoolQueryBuilder();
        if (ObjectUtil.isNotEmpty(searchHospitalParam.getCityId())) {
            booleanQueryBuilder.must(termQuery("cityId", searchHospitalParam.getCityId()));
        }
        if (ObjectUtil.isNotEmpty(searchHospitalParam.getName())) {
            booleanQueryBuilder.must(matchQuery("name", searchHospitalParam.getName()));
        }
        if (ObjectUtil.isNotEmpty(searchHospitalParam.getAddress())) {
            booleanQueryBuilder.should(termQuery("address", searchHospitalParam.getAddress()));
        }

        if (DESC.equals(searchHospitalParam.getSort())) {
            builder.withSort(new FieldSortBuilder("id").unmappedType("Long").order(SortOrder.DESC));
        } else if (ASC.equals(searchHospitalParam.getSort())) {
            builder.withSort(new FieldSortBuilder("id").unmappedType("Long").order(SortOrder.ASC));
        } else {
            builder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
        }

        SearchQuery searchQuery = builder
                .withQuery(booleanQueryBuilder)
                .withPageable(PageRequest.of(searchHospitalParam.getPage()-1, searchHospitalParam.getSize()))
                .build();

        Page<Hospital> result = hospitalRepository.search(searchQuery);

        List<SearchHospital> list = result.getContent().stream().map(product -> {
            SearchHospital searchHospital = new SearchHospital();
            searchHospital.setId(product.getId());
            searchHospital.setName(product.getName());
            searchHospital.setAddress(product.getAddress());
            searchHospital.setBrief(product.getBrief());
            searchHospital.setCityId(product.getCityId());
            searchHospital.setLat(product.getLat());
            searchHospital.setLng(product.getLng());
            return searchHospital;
        }).collect(Collectors.toList());
        Long count = result.getTotalElements();
        PageContext.setDataCount(count);
        PageContext.setPageSize(new Long(searchHospitalParam.getSize()));
        PageContext.setCurrentPage(new Long(searchHospitalParam.getPage()));
        PageBean<SearchHospital> searchItemPageBean = new PageBean<>(list);
        PageContext.clear();
        return searchItemPageBean;
    }
}
